﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Domain.MainModule.Entities;
using Domain.MainModule.GroupBranches;
using Domain.Core.Specification;
using Domain.Core;
using Domain.MainModule.Branches;
using Domain.MainModule.BillingInformations;

namespace Application.MainModule.GroupBranchesManagement
{
    public class GroupBranchManagementService: IGroupBranchManagementService, IDisposable
    {
        #region Members

        IGroupBranchRepository _GroupBranchRepository;
        IBillingInformationRepository _BillingInformationRepository;


        #endregion

        #region Constructor

        public GroupBranchManagementService(IGroupBranchRepository groupBranchRepository, IBillingInformationRepository billingInformationRepository)
        {
            if (groupBranchRepository == (IGroupBranchRepository)null)
                throw new ArgumentNullException(Resources.Messages.exception_DependenciesAreNotInitialized);

            if (billingInformationRepository == (IBillingInformationRepository)null)
                throw new ArgumentNullException(Resources.Messages.exception_DependenciesAreNotInitialized);

            _GroupBranchRepository = groupBranchRepository;
            _BillingInformationRepository = billingInformationRepository;
        }

        #endregion

        public void AddGroupBranch(GroupBranch groupBranch)
        {
            IUnitOfWork unitOfWork = _GroupBranchRepository.UnitOfWork as IUnitOfWork;
            _GroupBranchRepository.Add(groupBranch);
            unitOfWork.Commit();
        }

        public void ChangeGroupBranch(GroupBranch groupBranch)
        {
            IUnitOfWork unitOfWork = _GroupBranchRepository.UnitOfWork as IUnitOfWork;
            _GroupBranchRepository.Modify(groupBranch);
            unitOfWork.CommitAndRefreshChanges();
        }

        public void RemoveGroupBranch(GroupBranch groupBranch)
        {
            if (groupBranch == (GroupBranch)null)
            {
                throw new ArgumentNullException("groupBranch");
            }

            IUnitOfWork unitOfWork = _GroupBranchRepository.UnitOfWork as IUnitOfWork;
            _GroupBranchRepository.Remove(groupBranch);
            unitOfWork.CommitAndRefreshChanges();
        }

        public List<GroupBranch> FindGroupBranchByName(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException(Resources.Messages.exception_InvalidUserId, "name");
            }

            GroupBranchNamePrioritySpecification spec = new GroupBranchNamePrioritySpecification(name);
            return _GroupBranchRepository.FindGroupBranches(spec).ToList();
        }

        public GroupBranch FindGroupBranchByGroupBranchId(Guid groupBranchId)
        {
            GroupBranchGroupBranchIdSpecification spec = new GroupBranchGroupBranchIdSpecification(groupBranchId);
            return _GroupBranchRepository.FindGroupBranch(spec);
        }

        #region IDisposable

        /// <summary>
        /// Dispose associated context with this domain service
        /// </summary>
        public void Dispose()
        {
            if (_GroupBranchRepository != null
                &&
                _GroupBranchRepository.UnitOfWork != null)
            {
                _GroupBranchRepository.UnitOfWork.Dispose();
            }
        }

        #endregion

        public List<GroupBranch> FindPagedGroupBranches(int pageIndex, int pageCount)
        {
            if (pageIndex < 0)
            {
                throw new ArgumentException(Resources.Messages.exception_InvalidPageIndex, "pageIndex");
            }

            if (pageCount <= 0)
            {
                throw new ArgumentException(Resources.Messages.exception_InvalidPageCount, "pageCount");
            }

            Specification<GroupBranch> onlyEnabledSpec = new DirectSpecification<GroupBranch>(c=> c.Priority > 0);

            return _GroupBranchRepository.GetPagedElements(pageIndex, pageCount, c => c.Name, onlyEnabledSpec, true).ToList();

        }


        public List<BillingInformation> FindBillingInformation(string name, bool isCuit)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException(Resources.Messages.exception_InvalidArgument, "name");
            }

            if(isCuit)
            {
                BillingInformationCUITSpecification spec1 = new BillingInformationCUITSpecification(name);
                return _BillingInformationRepository.FindBillingInformations(spec1).ToList();
            }
            else
            {
                BillingInformationCompanyNameSpecification spec2 = new BillingInformationCompanyNameSpecification(name);
                return _BillingInformationRepository.FindBillingInformations(spec2).ToList();
            }
        }

        public List<BillingInformation> FindBillingInformationByGroupBranch(Guid groupBranchId)
        {
            BillingInformationGroupBranchIdSpecification spec = new BillingInformationGroupBranchIdSpecification(groupBranchId);
            return _BillingInformationRepository.FindBillingInformations(spec).ToList();
        }

        BillingInformation IGroupBranchManagementService.FindBillingInformationById(Guid billingInformationId)
        {
            BillingInformationBillingInformationIdSpecification spec = new BillingInformationBillingInformationIdSpecification(billingInformationId);

            return _BillingInformationRepository.FindBillingInformation(spec);
            
        }
    }
}
